﻿using System.Text.Json;
using iOSClub.CheckInApi.DataModels;
using iOSClub.CheckInApi.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace iOSClub.CheckInApi.Controllers;

[TokenActionFilter]
[Authorize]
[ApiController]
[Route("[controller]")]
public class CheckController(
    IDbContextFactory<CheckContext> factory,
    IHttpContextAccessor httpContextAccessor) : ControllerBase
{
    [HttpGet]
    public async Task<IActionResult> CheckIn()
    {
        await using var context = await factory.CreateDbContextAsync();
        var member = httpContextAccessor.HttpContext?.User.GetUser();
        if (member == null) return NotFound("用户未登录或验证已超时");
        member = await context.Users
            .Include(x => x.Checks)
            .FirstOrDefaultAsync(x => x.Id == member.Id && x.Name == member.Name);
        if (member == null) return NotFound("找不到用户");

        var model = new CheckModel
        {
            CheckTime = DateTime.Now
        };
        
        if (member.Checks.Any(x => x.CheckTime.Day == model.CheckTime.Day))
            return BadRequest("重复签到");

        model.User = member;
        model.Key = DataTool.StringToHash(model.ToString());
        if (!string.IsNullOrEmpty(model.SeriesId))
        {
            var series = await context.Series.Include(seriesModel => seriesModel.Users)
                .FirstOrDefaultAsync(x => x.Key == model.SeriesId);
            if (series == null) return NotFound("找不到签到组");
            if (!series.Users.Contains(member)) return BadRequest("用户不在签到组内");
            model.Series = series;
        }

        context.Checks.Add(model);
        await context.SaveChangesAsync();

        return Ok(model.Key);
    }

    [HttpPost("/Check/Change")]
    public async Task<IActionResult> ChangeCheck([FromBody] CheckModel model)
    {
        await using var context = await factory.CreateDbContextAsync();
        var member = httpContextAccessor.HttpContext?.User.GetUser();
        if (member == null) return NotFound("用户未登录或验证已超时");
        member = await context.Users.FirstOrDefaultAsync(x => x.Id == member.Id && x.Name == member.Name);
        if (member == null) return NotFound("找不到用户");

        var check = await context.Checks.FirstOrDefaultAsync(x => x.Key == model.Key);
        if (check == null) return NotFound("找不到签到记录");
        if (check.UserId != member.Id) return BadRequest("用户没有权限修改签到记录");
        check.Update(model);

        await context.SaveChangesAsync();
        return Ok();
    }

    [HttpGet("/Check/Today")]
    public async Task<ActionResult<string>> GetTodayCheck()
    {
        await using var context = await factory.CreateDbContextAsync();
        var member = httpContextAccessor.HttpContext?.User.GetUser();
        if (member == null) return NotFound("用户未登录或验证已超时");
        member = await context.Users.FirstOrDefaultAsync(x => x.Id == member.Id && x.Name == member.Name);
        if (member == null) return NotFound("找不到用户");

        var today = await context.Checks.Where(x => x.CheckTime.Day == DateTime.Now.AddHours(8).Day).ToListAsync();

        return Convert.ToBase64String(GZipServer.Compress(JsonSerializer.SerializeToUtf8Bytes(today)));
    }

    [HttpGet("/Check/Series/{id}")]
    public async Task<ActionResult<string>> GetAllCheck(string id)
    {
        await using var context = await factory.CreateDbContextAsync();
        var member = httpContextAccessor.HttpContext?.User.GetUser();
        if (member == null) return NotFound("用户未登录或验证已超时");
        member = await context.Users.FirstOrDefaultAsync(x => x.Id == member.Id && x.Name == member.Name);
        if (member == null) return NotFound("找不到用户");

        var series = await context.Series.Include(seriesModel => seriesModel.Checks)
            .FirstOrDefaultAsync(x => x.Key == id);

        if (series == null) return NotFound("找不到签到组");
        var today = series.Checks.Where(x => x.CheckTime.Day == DateTime.Now.AddHours(8).Day);
        return Convert.ToBase64String(GZipServer.Compress(JsonSerializer.SerializeToUtf8Bytes(today)));
    }
}